// topiclist.go
package main

import (
	"fmt"
	"regexp"
	"strconv"

	"github.com/PuerkitoBio/goquery"
	log "github.com/alecthomas/log4go"
)

type TopicList struct {
	boardUrl    string
	lastTopicId int
	topicList   []int
	err         error
	postFunc    func(out *TopicList)
}

var topicIdReg *regexp.Regexp = regexp.MustCompile(`\/(\d+)\.html?`)

func CreateTopicList(boardUrl string, lastTopicId int, postFunc func(out *TopicList)) *TopicList {
	ret := &TopicList{}
	ret.boardUrl = boardUrl
	ret.lastTopicId = lastTopicId
	ret.postFunc = postFunc
	return ret
}

func (self *TopicList) post() {
	if self.err == nil && self.postFunc != nil {
		self.postFunc(self)
	}
}

func (self *TopicList) run() {
	page := 0

	topicList := []int{}
	self.err = nil

	topicId := int(^uint(0) >> 1) // max val
	maxTopicId := self.lastTopicId

	for topicId > self.lastTopicId {
		page++
		url := fmt.Sprintf("https://bbs.hupu.com%s-postdate-%d", self.boardUrl, page)
		doc, err := goquery.NewDocument(url)

		if err != nil {
			log.Error("Cannot query topics from url:%s, %v", url, err)
			self.err = err
			return
		}

		hasTopic := false
		doc.Find(".titlelink.box").EachWithBreak(
			func(i int, contentSelection *goquery.Selection) bool {
				hasTopic = true
				isTop := contentSelection.Find("span:contains(置顶)").Length() != 0
				if isTop && 0 == self.lastTopicId {
					// at the first round, we ignore any top topic
					return true
				}

				topicUrl, exists := contentSelection.Find("a.truetit").Attr("href")
				if !exists {
					return true
				}

				topicId, err = strconv.Atoi(topicIdReg.ReplaceAllString(topicUrl, "$1"))
				if err != nil {
					log.Error("Cannot convert topic id %s, %v", topicUrl, err)
					return false
				}

				if topicId <= self.lastTopicId {
					// we found older topic, break if it is top
					return isTop
				}

				topicList = append(topicList, topicId)
				log.Trace("Appended topic id: %d", topicId)
				if maxTopicId < topicId {
					maxTopicId = topicId
				}

				return self.lastTopicId != 0
			})

		log.Info("Fetched url: %s, last topicId: %d", url, topicId)

		// we walked around the first page,
		// if that's first time, no matter if we have any topic found, just stop it
		if self.lastTopicId == 0 {
			break
		}

		if !hasTopic {
			log.Error("No topic found at url: %s", url)
			break
		}
	}

	self.lastTopicId = maxTopicId
	self.topicList = topicList
}
